﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using Netron.Diagramming.Core;
using Netron.Diagramming.Win;
using Faml;
using Faml.Optimization;
using Faml.LinqCompiler;
using Faml.Frontend;
using Faml.Compiler;
using DAI.ClientToolkit;
using System.Xml;
using System.Collections.Specialized;
using System.Collections;

namespace VisualFaml
{
    public partial class Form1 : Form
    {
        private RuntimeEnvironment runtimeEnvironment;

        private int baseops = 0;
        private int assemblies = 0;


        System.Threading.Timer timerAlign;


        private List<DiagramControl> diagrams;
        private List<List<ShapeBase>> shapes;


        public Form1()
        {
            shapes = new List<List<ShapeBase>>();
            diagrams = new List<DiagramControl>();

            InitializeComponent();

            timerAlign = new System.Threading.Timer(new TimerCallback(AlignShapes), null, Timeout.Infinite, Timeout.Infinite);
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            
            try
            {
                dwListener = new DebugWindowListener();
                System.Diagnostics.Debug.Listeners.Add(dwListener);
                System.Diagnostics.Debug.Listeners.Add(new TextWriterTraceListener(logSaveTo));
                System.Diagnostics.Debug.AutoFlush = true;
            }
            catch (Exception exc)
            {
                MessageBox.Show(exc.Message);
            }


            try
            {
                runtimeEnvironment = RuntimeEnvironment.GetDefaultRuntimeEnvironment();

                this.baseops = runtimeEnvironment.OperationCount;
                this.assemblies = runtimeEnvironment.AssemblyCount;
                UpdateAddedLibs();

                toolOptimizationSwitch.Checked = false;
                toolOptimizationSwitch.Checked = true;
                toolDebugWnd.Checked = false;                
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }

        }

        private void UpdateAddedLibs()
        {
            toolStripAddedLibsList.Text = string.Format("{0} operation(s)/{1} assemblies", runtimeEnvironment.OperationCount, assemblies);
        }

        private void toolStripDropDownButton1_Click(object sender, EventArgs e)
        {

        }

        private void buildGraphToolStripMenuItem_Click(object sender, EventArgs e)
        {
            resultExpression.ClearAll();
            BuildExpressionGraph(FamlProgram.Compile(runtimeEnvironment, expression.Text));
        }

        private void Eval(string expression)
        {
            output.ClearAll();
            resultExpression.ClearAll();

            if (oGSADAIToolStripMenuItem.Checked)
            {
                EvalOGSADAI(expression);
            }
            else
            {
                FamlProgram faml = FamlProgram.Compile(runtimeEnvironment, expression);
                Eval(faml);
            }
        }

        private XmlDocument PreparePerformDoc(string faml)
        {
            string doc = "<?xml version=\"1.0\" ?>" +
                "<perform xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns=\"http://ogsadai.org.uk/namespaces/2005/10/types\">" +
                "<FamlActivity name=\"famlExpression\">" +
                "<output name=\"famlResult\" />" +
                "<faml><![CDATA[" + faml + "]]></faml></FamlActivity></perform>";
            XmlDocument perform = new XmlDocument();
            perform.LoadXml(doc);
            return perform;
        }

        private void EvalOGSADAI(string expression)
        {
            try
            {
                string url = ogsaDaiUrl.Text;

                output.Put("Sending perform document to OGSA DAI service {0}...", url);
                DataServiceResource esse = new DataService(url).DataServiceResource("EsseCdmResource");
                XmlDocument perform = PreparePerformDoc(expression);

                output.Put("Evaluation...");

                DateTime now = DateTime.Now;
                XmlElement resp = esse.Perform(perform, null);
                TimeSpan delta = DateTime.Now - now;

                output.Put("Evaluation complete ({0})\n============================================================\n\n",
                    TimeToString(delta));

                XmlNamespaceManager ns = new XmlNamespaceManager(new NameTable());
                ns.AddNamespace("t", Namespaces.Types);
                string result = ((XmlElement)resp.SelectSingleNode("//t:result[@name='famlResult']", ns)).InnerText;

                output.Put(result);
            }
            catch (Exception ex)
            {
                output.Put(ex);
            }
        }

        private void PrintArray(Array array, StringBuilder sb)
        {
            Array a = array;

            if (a.Rank == 1)
            {
                if (a.Length == 0)
                    sb.AppendLine("--empty--");
                else if (a.GetValue(0) is Array)
                {
                    for (int i = 0; i < a.Length; i++)
                        PrintArray(a.GetValue(i) as Array, sb);
                    sb.AppendLine();
                }
                else
                {
                    for (int i = 0; i < a.Length; i++)
                        sb.AppendFormat("{0} ", a.GetValue(i));
                    sb.AppendLine();
                }
            }
            else if (a.Rank == 2)
            {
                for (int i = 0; i < a.GetLength(0); i++)
                {
                    for (int j = 0; j < a.GetLength(1); j++)
                        sb.AppendFormat("{0} ", a.GetValue(i, j));
                    sb.AppendLine();
                }
            }
            else if (a.Rank == 3)
            {
                for (int i = 0; i < a.GetLength(0); i++)
                {
                    for (int j = 0; j < a.GetLength(1); j++)
                    {
                        for (int k = 0; k < a.GetLength(2); k++)
                        {
                            sb.AppendFormat("{0} ", a.GetValue(i, j, k));
                        }
                        sb.AppendLine();
                    }
                    sb.AppendLine();
                }
            }
        }

        private DiagramControl CreateDiagram(int n)
        {
            DiagramControl dc = new DiagramControl();

            dc.AllowDrop = true;
            dc.AutoScroll = true;
            dc.AutoScrollMinSize = new System.Drawing.Size(50000, 50000);
            dc.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(192)))), ((int)(((byte)(255)))), ((int)(((byte)(192)))));
            dc.BackgroundType = Netron.Diagramming.Core.CanvasBackgroundTypes.FlatColor;
            dc.Dock = System.Windows.Forms.DockStyle.Fill;
            dc.EnableAddConnection = true;
            dc.Location = new Point(0, 0);
            dc.Magnification = new System.Drawing.SizeF(80F, 80F);
            dc.Name = string.Format("Expression {0}", n+1);
            dc.Origin = new Point(0, 0);
            dc.ShowPage = false;
            dc.ShowRulers = false;
            dc.Size = new System.Drawing.Size(878, 422);
            dc.TabIndex = 1;
            dc.Text = dc.Name;

            diagrams.Add(dc);
            shapes.Add(new List<ShapeBase>());

            TabPage page = new TabPage(dc.Text);
            page.Controls.Add(dc);
            this.tabDiagrams.TabPages.Add(page);

            return dc;
        }

        private string TimeToString(TimeSpan delta)
        {
            return string.Format("{0}:{1}:{2:F6}", delta.Hours, delta.Minutes, delta.Seconds + delta.Milliseconds / 1000.0);
        }

        private void Eval(FamlProgram faml)
        {
            try
            {               
                if (faml == null) return;
                resultExpression.ClearAll();
                faml.SubExpressionAdded += new SubExpressionAddedHandler(faml_SubExpressionAdded);
                
                DateTime now = DateTime.Now;

                object result = faml.Evaluate();

                TimeSpan delta = DateTime.Now - now;
           
                output.Put("Evaluation complete (pure: {0}, total: {1})\n============================================================\n\n", 
                    TimeToString(faml.TimeEvaluation), TimeToString(delta));

                output.Put(string.Format("Type inferred from expression: {0}\n\n", faml.InferredType));

                StringBuilder sb = new StringBuilder();
                PrintHelper.PrintValue(sb, result);
                output.Put(sb.ToString());

            }
            catch (Exception ex)
            {
                output.Put(ex);
            }
        }

        private void PrintResult(object result, StringBuilder sb)
        {
            if (result is OrderedDictionary)
            {
                OrderedDictionary dict = (OrderedDictionary)result;
                sb.Append("{\n");
                foreach (DictionaryEntry item in dict)
                {
                    sb.AppendFormat("\t{0} = ", item.Key);
                    PrintResult(item.Value, sb);
                    sb.AppendLine();
                }
                sb.Append("}\n");
            }
            else if (result is Array)
            {
                PrintArray(result as Array, sb);
            }
            else
            {
                sb.AppendFormat("{0}", result);
            }
        }

        private void faml_SubExpressionAdded(object sender, SubExpressionAddedEventArgs e)
        {
            resultExpression.Put(e.SubExpression.Name + " = " + e.SubExpression.Expression.ToString());
            resultExpression.Put("\n\n");
        }


        private ShapeBase BuildExpressionGraph(FamlProgram program)
        {
            shapes.Clear();
            diagrams.Clear();
            TabPage page0 = tabDiagrams.TabPages[0];
            tabDiagrams.TabPages.Clear();
            tabDiagrams.TabPages.Add(page0);
            tabDiagrams.Visible = true;
            

            if (program == null) return null;

            //ShapeBase root = null;

            ////ExpressionMetadata<ExpressionNodeExtension> metadata;
            ////for (int i = 0; i < program.Sequences.Count; i++)
            ////    CreateDiagram(i);

            ////for (int i = program.Sequences.Count; --i >= 0; )
            ////{
            ////    Expression expr = program.Sequences[i];

            ////    metadata = ExpressionOptimizer.MakeMetadata(expr);
            ////    root = BuildExpressionGraphNonRoot(i, expr, metadata);

            ////    diagrams[i].SetLayoutRoot(root);
            ////    diagrams[i].Layout(LayoutType.ClassicTree);
            ////}
                        
            //resultExpression.Put(program.OutputExpression);
            //for (int i = 0; i < program.Sequences.Count; i++)
            //{
            //    Expression expr = program.Sequences[i];

            //    string with = "";

            //    with = expr.ToString() + "\n";
            //    if (i < program.Sequences.Count - 1)
            //        with = "with\n\tex" + (i + 1).ToString() + " = " + with;
            //    else
            //        with = "\n\n" + with;

            //    resultExpression.Put(with);
            //}
                                    
            //timerAlign.Change(700, Timeout.Infinite);
            //return root;
            return null;
        }

        //private ShapeBase BuildExpressionGraphNonRoot(int n, Expression exp, ExpressionMetadata<ExpressionNodeExtension> metadata)
        //{
        //    ExpressionNodeExtension ext = metadata[exp];

        //    ClassShape shape = new ClassShape();           
        //    shape.SubTitle = TrimString("Type: " + exp.Type.ToString(), 30);

        //    shape.BodyType = BodyType.List;
        //    shape.PropertiesNode.Entries.Clear();
        //    shape.PropertiesNode.Text = "Parameters";
        //    foreach (ParameterExpression param in ext.DependsOnParameters)
        //    {
        //        shape.PropertiesNode.Entries.Add(new LabelMaterial(param.Name + " (" + param.Type + ")"));
        //    }


        //    shape.MethodsNode.Entries.Clear();
        //    shape.MethodsNode.Text = "Info";
        //    shape.MethodsNode.Visible = true;
        //    shape.MethodsNode.Entries.Add(
        //        new LabelMaterial("Height: " + ext.Height.ToString()));
        //    shape.MethodsNode.Entries.Add(
        //        new LabelMaterial("Hash: " + ext.Hash.ToString()));
        //    shape.MethodsNode.Entries.Add(
        //        new LabelMaterial("Node Type: " + exp.NodeType.ToString()));
        //    shape.MethodsNode.Entries.Add(
        //         new LabelMaterial("CLR Type: " + exp.GetType().Name));

        //    shape.Expand();
        //    shape.PropertiesNode.Expand();
        //    shape.MethodsNode.Expand();


        //    if (exp is LambdaExpression)
        //    {
        //        LambdaExpression lexp = (LambdaExpression)exp;

        //        string s = TrimString(lexp.ToString(), 15);
        //        shape.Title = s;

        //        ShapeBase bodyshape = BuildExpressionGraphNonRoot(n, lexp.Body, metadata);
        //        diagrams[n].AddConnection(shape.Connectors[1], bodyshape.Connectors[0]);
        //    }
        //    else if (exp is MethodCallExpression)
        //    {
        //        MethodCallExpression mce = (MethodCallExpression)exp;

        //        if (mce.Method.Name == "GetResult")
        //        {
        //            ConstantExpression exn = (ConstantExpression)mce.Arguments[0];
        //            shape.Title = string.Format("Expression {0}", ((int)exn.Value)+1);
        //            shape.HeadColor = Color.Salmon;
        //        }
        //        else
        //        {
        //            shape.Title = mce.Method.Name;

        //            foreach (Expression arg in mce.Arguments)
        //            {
        //                ShapeBase argshape = BuildExpressionGraphNonRoot(n, arg, metadata);

        //                diagrams[n].AddConnection(shape.Connectors[1], argshape.Connectors[0]);
        //            }
        //        }
        //    }
        //    else if (exp is ConstantExpression)
        //    {
        //        ConstantExpression ce = (ConstantExpression)exp;

        //        shape.Title = ce.Value.ToString();
        //    }
        //    else if (exp is MemberExpression)
        //    {
        //        MemberExpression me = (MemberExpression)exp;
        //        shape.Title = TrimString(me.Expression.ToString(), 20) + "." + me.Member.Name;

        //        if (CheckToDescend(me.Expression))
        //        {
        //            ShapeBase argshape = BuildExpressionGraphNonRoot(n, me.Expression, metadata);
        //            diagrams[n].AddConnection(shape.Connectors[1], argshape.Connectors[0]);
        //        }
                
        //    }
        //    else if (exp is UnaryExpression)
        //    {
        //        UnaryExpression ue = (UnaryExpression)exp;
        //        shape.Title = TrimString(exp.ToString(), 100);

        //        if (CheckToDescend(ue.Operand))
        //        {
        //            ShapeBase argshape = BuildExpressionGraphNonRoot(n, ue.Operand, metadata);
        //            //shape = argshape as ClassShape;
        //            diagrams[n].AddConnection(shape.Connectors[1], argshape.Connectors[0]);
        //        }
        //    }
        //    else if (exp is BinaryExpression)
        //    {
        //        BinaryExpression be = (BinaryExpression)exp;
        //        shape.Title = be.NodeType.ToString();//TrimString(exp.ToString(), 100);

        //        bool b = CheckToDescend(be.Left) || CheckToDescend(be.Right);
        //        if (b)
        //        {
        //            ShapeBase argshape = BuildExpressionGraphNonRoot(n, be.Left, metadata);
        //            diagrams[n].AddConnection(shape.Connectors[1], argshape.Connectors[0]);
                    
        //            argshape = BuildExpressionGraphNonRoot(n, be.Right, metadata);
        //            diagrams[n].AddConnection(shape.Connectors[1], argshape.Connectors[0]);
        //        }

        //        if (!b)
        //        {
        //            shape.Title = be.ToString();
        //        }
        //    }
        //    else if (exp is InvocationExpression)
        //    {
        //        InvocationExpression ie = (InvocationExpression)exp;
        //        shape.Title = "Invoke " + TrimString(ie.Expression.ToString(), 100);

        //        ShapeBase argshape = BuildExpressionGraphNonRoot(n, ie.Expression, metadata);
        //        diagrams[n].AddConnection(shape.Connectors[1], argshape.Connectors[0]);
                
        //        foreach (Expression arg in ie.Arguments)
        //        {
        //            argshape = BuildExpressionGraphNonRoot(n, arg, metadata);
        //            diagrams[n].AddConnection(shape.Connectors[2], argshape.Connectors[0]);
        //        }
        //    }
        //    else
        //    {
        //        shape.Title = exp.ToString();
        //    }

        //    diagrams[n].AddShape(shape);

        //    shapes[n].Add(shape);
        //    return shape;
        //}

        private bool CheckToDescend(Expression exp)
        {
            if (exp is LambdaExpression)
            {
                return CheckToDescend(((LambdaExpression)exp).Body);
            }
            else if (exp is MethodCallExpression)
            {
                MethodCallExpression mce = (MethodCallExpression)exp;

                return true;
            }
            else if (exp is ConstantExpression)
            {
                return false;
            }
            else if (exp is MemberExpression)
            {
                MemberExpression me = (MemberExpression)exp;
                return CheckToDescend(me.Expression);
            }
            else if (exp is UnaryExpression)
            {
                UnaryExpression ue = (UnaryExpression)exp;
                return CheckToDescend(ue.Operand);
            }
            else if (exp is BinaryExpression)
            {
                BinaryExpression be = (BinaryExpression)exp;
                return CheckToDescend(be.Left) || CheckToDescend(be.Right);
            }
            else if (exp is InvocationExpression)
            {
                InvocationExpression ie = (InvocationExpression)exp;

                if (CheckToDescend(ie.Expression)) return true;

                foreach (Expression arg in ie.Arguments)
                {
                    if (CheckToDescend(arg))
                        return true;
                }
            }

            return false;
        }

        private delegate void AlignShapesDel(object target);

        private void AlignShapes(object target)
        {
            if (diagrams == null || diagrams.Count == 0) return;

            if (diagrams[0].InvokeRequired)
            {
                diagrams[0].Invoke(new AlignShapesDel(AlignShapes), target);
                return;
            }

            tabDiagrams.SelectedIndex = 1;

            for (int n = 0; n < shapes.Count; n++)
            {
                int left = 0;
                int top = 0;
                int right = 0;
                int bottom = 0;

                foreach (ShapeBase s in shapes[n])
                {
                    if (s.Location.X < left)
                        left = s.Location.X;
                    else if (s.Location.X > right)
                        right = s.Location.X;
                    if (s.Location.Y < top)
                        top = s.Location.Y;
                    else if (s.Location.Y > bottom)
                        bottom = s.Location.Y;
                }

                if (left < 0 || top < 0)
                {
                    left -= 5;
                    top -= 5;

                    foreach (ShapeBase s in shapes[n])
                    {
                        s.Location = new Point(s.Location.X - left, s.Location.Y - top);
                    }
                }

                diagrams[n].AutoScrollMinSize = new Size(right - left + 10, bottom - top + 10);
                diagrams[n].Invalidate();
            }
        }

        private void Form1_Shown(object sender, EventArgs e)
        {
            this.statusLibrary.Text = runtimeEnvironment.OperationLibrary.GetStatistics();
        }

        private string TrimString(string s, int n)
        {
            if (s.Length < n) return s;
            return s.Substring(0, n - 3) + "...";
        }

        private FamlProgram GetFamlProgram(string expression)
        {
            output.ClearAll();

            try
            {
                DateTime now = DateTime.Now; 
                FamlProgram faml = FamlProgram.Compile(runtimeEnvironment, expression);
                TimeSpan delta = DateTime.Now - now;

                output.Put("Compile complete ({0})", TimeToString(delta));

                return faml;
            }
            catch (Exception ex)
            {
                output.Put(ex);
            }
            return null;

            //try
            //{
            //    /******** Precompile *********/
            //    DateTime now = DateTime.Now; 
            //    Compiler precompiler = new Compiler();
            //    ExpressionParser mparser = new ExpressionParser(expression);
            //    mparser.MoveNext();
            //    FamlExpression macro = precompiler.Precompile(mparser);                

            //    TimeSpan delta = DateTime.Now - now;
            //    output.Put("Precompile complete ({0})", TimeToString(delta));

            //    expression = macro.ToString();
            //    Debug.WriteLine("Macro-expanded expression: " + expression);

            //    /******** Compile *********/
            //    now = DateTime.Now;

            //    Expression lexp = LinqExpressionCompiler.Compile(macro);

            //    delta = DateTime.Now - now;
            //    output.Put("Compile complete ({0})", TimeToString(delta));


            //    /******** Optimize *********/
            //    DartProgram program;

            //    if (toolOptimizationSwitch.Checked)
            //    {
            //        IVisitor mergeVisitor = new MergeVisitor(mergeTable);
            //        IVisitor getlensubVisitor = new GetLengthSubarrayVisitor();

            //        ExpressionOptimizer optimizer = new ExpressionOptimizer(lexp);
            //        optimizer.AddVisitor(getlensubVisitor);
            //        optimizer.AddVisitor(mergeVisitor);

            //        now = DateTime.Now;

            //        program = optimizer.Optimize();

            //        delta = DateTime.Now - now;
            //        output.Put("Optimization complete ({0})", TimeToString(delta));
            //    }
            //    else
            //    {
            //        program = new DartProgram(lexp);
            //    }

            //    return program;
            //}
            //catch (Exception ex)
            //{
            //    output.Put(ex);
            //}
            //return null;
        }

        private void evaluateBuildToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Eval(expression.Text);
        }

        private void evaluateToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Eval(expression.Text);
        }

        private void output_TextChanged(object sender, EventArgs e)
        {

        }

        private void toolStripAddedLibs_SelectedIndexChanged(object sender, EventArgs e)
        {
            UpdateAddedLibs();
        }

        private void optimizeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //try
            //{
            //    DartProgram dart = GetFamlProgram(expression.Text);

            //    if (dart != null)
            //    {
            //        BuildExpressionGraph(dart);
            //        Eval(dart);
            //    }
            //}
            //catch (Exception exc)
            //{
            //    MessageBox.Show(exc.Message);
            //}
        }

        private void toolOptimizationSwitch_CheckedChanged(object sender, EventArgs e)
        {
            toolOptimizationSwitch.Text = string.Format("Optimizations ({0}): {1}", runtimeEnvironment.MergeTable.OptimizationsCount,
                toolOptimizationSwitch.Checked ? "On" : "Off");
        }

        private DebugWindowListener dwListener;
        private DebugWindow debugWnd;
        private string logSaveTo = Path.GetFullPath("log.txt");

        private void toolDebugWnd_CheckedChanged(object sender, EventArgs e)
        {
            if (debugWnd != null)
            {
                if (toolDebugWnd.Checked)
                {
                    debugWnd.Activate();
                }
                else
                {
                    debugWnd.Close();
                    debugWnd.Dispose();
                    debugWnd = null;
                }
            }
            else
            {
                if (toolDebugWnd.Checked)
                {
                    debugWnd = new DebugWindow();
                    debugWnd.FormClosed += new FormClosedEventHandler(debugWnd_Disposed);
                    debugWnd.Disposed += new EventHandler(debugWnd_Disposed);
                    debugWnd.SaveTo = logSaveTo;
                    debugWnd.Listener = dwListener;
                    debugWnd.Show();
                }
                else
                {                    
                }
            }
        }

        void debugWnd_Disposed(object sender, EventArgs e)
        {
            debugWnd = null;
            if (toolDebugWnd.Checked == true)
                toolDebugWnd.Checked = false;
        }

        private void toolDebugWnd_Click(object sender, EventArgs e)
        {

        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            timerAlign.Dispose();
        }

        private void expression_KeyUp(object sender, KeyEventArgs e)
        {
            this.toolStripCurrentChar.Text = "Char: " + ((int)(this.expression.SelectionStart+1)).ToString();
        }

        private void expression_MouseClick(object sender, MouseEventArgs e)
        {
            this.toolStripCurrentChar.Text = "Char: " + ((int)(this.expression.SelectionStart + 1)).ToString();
        }

        private void expression_KeyDown(object sender, KeyEventArgs e)
        {
            this.toolStripCurrentChar.Text = "Char: " + ((int)(this.expression.SelectionStart + 1)).ToString();
        }

        private void toolStripExpressionSelectAll_Click(object sender, EventArgs e)
        {
            this.expression.SelectAll();
        }

        private void toolStripExpressionCopyToClipboard_Click(object sender, EventArgs e)
        {
            Clipboard.SetData(DataFormats.StringFormat, this.expression.Text);
        }

        private void toolStripExpressionClear_Click(object sender, EventArgs e)
        {
            this.expression.Clear();
        }

        private string fileSave = "";

        private void saveAsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SaveFileDialog sfd = new SaveFileDialog();
            sfd.FileName = Path.GetFileName(fileSave);
            //sfd.InitialDirectory = Path.GetDirectoryName(fileSave);

            sfd.Filter = "Faml Queries (*.faml)|*.faml|Text Files (*.txt)|*.txt|All Files|*.*||";
            sfd.OverwritePrompt = true;

            if (sfd.ShowDialog() == DialogResult.OK)
            {
                using (StreamWriter sw = new StreamWriter(fileSave = sfd.FileName, false))
                {
                    sw.Write(this.expression.Text);
                }                
            }
        }

        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog fd = new OpenFileDialog();
            fd.FileName = Path.GetFileName(fileSave);
            //fd.InitialDirectory = Path.GetDirectoryName(fileSave);

            fd.Filter = "Faml Queries (*.faml)|*.faml|Text Files (*.txt)|*.txt|All Files|*.*||";

            if (fd.ShowDialog() == DialogResult.OK)
            {
                using (StreamReader sw = new StreamReader(fileSave = fd.FileName))
                {
                    this.expression.Lines = sw.ReadToEnd().Split('\n');
                }
            }
        }

        private void ptToolStripMenuItem_Click(object sender, EventArgs e)
        {
            foreach (ToolStripMenuItem item in toolStripFontSizeMenu.DropDownItems)
            {
                item.Checked = sender == item;
            }

            float size = (int)((sender as ToolStripDropDownItem).Tag);
            Font font = this.expression.Font;
            font = new Font(font.FontFamily, size);

            this.expression.Font = font;
        }

        private void localToolStripMenuItem_Click(object sender, EventArgs e)
        {
            localToolStripMenuItem.Checked = !localToolStripMenuItem.Checked;
            oGSADAIToolStripMenuItem.Checked = !localToolStripMenuItem.Checked;
        }

        private void oGSADAIToolStripMenuItem_Click(object sender, EventArgs e)
        {
            oGSADAIToolStripMenuItem.Checked = !oGSADAIToolStripMenuItem.Checked;
            localToolStripMenuItem.Checked = !oGSADAIToolStripMenuItem.Checked;
            
        }

        private void ogsaDaiAddressToolStripMenuItem_Click(object sender, EventArgs e)
        {

        }

        private void ogsaDaiAddressToolStripMenuItem_DropDownClosed(object sender, EventArgs e)
        {
            if (VisualFaml.Properties.Settings.Default.OGSADAIUrl != ogsaDaiUrl.Text)
            {
                VisualFaml.Properties.Settings.Default.OGSADAIUrl = ogsaDaiUrl.Text;
                VisualFaml.Properties.Settings.Default.Save();
            }
        }
    }
}
